﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Services.Client;
using System.Globalization;
using System.IO;
using System.Linq;
using Citi.Helpers;
using Citi.Helpers.Extensions;
using Citi.RoutineBase;
using Citi.TasksAutomation.Domain.EmailSenderWcf;
using Citi.TasksAutomation.Domain.Sharepoint.OTFPC;
using OfficeOpenXml;

namespace Citi.TasksAutomation.Domain
{
    public class Task
    {
        public Task()
        {
            Emails = new List<Email>();
        }

        public const string PathFolder = @"\\LACBRA001FS0010\DATA_GRP1\FINTOOLS\Config\Controls\TasksAutomation\";
        public static PlanningProcessesDataContext dataContext;
        public List<EmailSenderWcf.Email> Emails { get; set; }

        public static PlanningProcessesDataContext DataContext
        {
            get
            {
                if (dataContext == null)
                    dataContext = new PlanningProcessesDataContext(new Uri("https://globalconsumer.collaborationtools.consumer.citigroup.net/sites/OTFPCPI/_vti_bin/ListData.svc"));

                dataContext.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

                return dataContext;
            }
        }

        public IEnumerable<TasksDeliverablesItem> GetAllTasks()
        {
            var response = DataContext.TasksDeliverables.Execute() as QueryOperationResponse<TasksDeliverablesItem>;
            var cloudsList = response.ToList();

            try
            {
                QueryOperationResponse<TasksDeliverablesItem> responseCont = null;
                var token = response.GetContinuation();

                while (token != null)
                {
                    responseCont = DataContext.Execute<TasksDeliverablesItem>(token) as QueryOperationResponse<TasksDeliverablesItem>;

                    cloudsList.AddRange(responseCont);
                    token = responseCont.GetContinuation();
                }
            }
            catch
            {

            }

            return cloudsList;
        }

        public IEnumerable<TasksDeliverablesItem> GetByMonth(int month, int year)
        {
            return GetAllTasks().Where(x => x.TargetDate.HasValue && x.TargetDate.Value.Month == month && x.TargetDate.Value.Year == year);
        }

        public IEnumerable<TasksDeliverablesItem> GetByWeek()
        {
            int weekOfYear = DateTime.Now.WeekOfYear();

            return GetAllTasks().Where(x => x.TargetDate.HasValue && x.TargetDate.Value.WeekOfYear() == weekOfYear);
        }

        public void SendUserNotification(IEnumerable<TasksDeliverablesItem> tasks, ref ICurrentAction currentAction)
        {
            var users = new List<UserInformationListItem>();
            var tasksUpdated = new List<TasksDeliverablesItem>();

            currentAction.Description = "Loading users";
            tasks.ToList().ForEach(x => UpdateTaskAndLoadAssignedTo(users, tasksUpdated, x));

            tasks = tasksUpdated;

            currentAction.Description = "Send User Notification";

            foreach (var item in users.Distinct())
            {
                System.Console.WriteLine(string.Concat("Generate e-mail: ", item.Name));

                var template = EmailHelper.GetEmailBody(@"\\LACBRA001FS0010\DATA_GRP1\FTOOLS\Apps\CalendarAutomation\HTML\UserNotification.htm");
                var templateContent = EmailHelper.GetEmailBody(@"\\LACBRA001FS0010\DATA_GRP1\FTOOLS\Apps\CalendarAutomation\HTML\UserNotificationContent.htm");

                template = FillNotificationContentTemplate("BAU", tasks, item, template, templateContent);
                //template = FillNotificationContentTemplate("VOE", tasks, item, template, templateContent);

                template = template.Replace("[FullName]", string.Format("{0} {1}", item.FirstName, item.LastName));
                template = template.Replace("[DateTime]", DateTime.Today.ToString("dd-MM-yyyy", new CultureInfo("pt-BR")));

                InsertEmailInQueue(template, string.Concat("FP&C Task Calendar – Weekly Inbox @ ", DateTime.Today.ToString("dd/MM/yyyy")), item.WorkEMail, string.Empty);
            }

            CreateControlFile("Notification");
        }

        public string FillNotificationContentTemplate(string activityType, IEnumerable<TasksDeliverablesItem> tasks, UserInformationListItem item, string template, string templateContent)
        {
            var filledTemplate = string.Empty;
            var tasksActivity = tasks.Where(x => x.ActivityTypeValue == activityType && (item == null || x.AssignedTo.Any(y => y == item)));

            foreach (var task in tasksActivity)
                filledTemplate += ReplaceNotificationContent(templateContent, task);

            template = template.Replace(string.Format("[Display{0}]", activityType), tasksActivity.Any() ? "block" : "none");
            template = template.Replace(string.Format("[{0}Notification]", activityType), filledTemplate);

            return template;
        }

        public void SendFollowUpNotification(IEnumerable<TasksDeliverablesItem> tasks, ref ICurrentAction currentAction)
        {
            currentAction.Description = "Follow Up Start";

            var users = new List<UserInformationListItem>();
            var tasksUpdated = new List<TasksDeliverablesItem>().ToList();

            tasks.Where(x => x.TargetDate < DateTime.Today && x.Complete != 1 && x.StatusValue != "Cancelled" && x.StatusValue != "Completed").ToList().ForEach(x => UpdateTaskAndLoadAssignedTo(users, tasksUpdated, x));
            tasks = tasksUpdated;
            var templateMaster = EmailHelper.GetEmailBody(@"\\LACBRA001FS0010\DATA_GRP1\FTOOLS\Apps\CalendarAutomation\HTML\FUPNotification.htm");
            var templateContentMaster = EmailHelper.GetEmailBody(@"\\LACBRA001FS0010\DATA_GRP1\FTOOLS\Apps\CalendarAutomation\HTML\FUPNotificationContent.htm");

            foreach (var item in users.Distinct())
            {
                currentAction.Description = string.Concat("Generate e-mail: ", item.Name);

                var template = templateMaster;
                var templateContent = templateContentMaster;

                template = FillNotificationContentTemplate("BAU", tasks, item, template, templateContent);
                //template = FillNotificationContentTemplate("VOE", tasks, item, template, templateContent);

                template = template.Replace("[FullName]", string.Format("{0} {1}", item.FirstName, item.LastName));
                template = template.Replace("[DateTime]", DateTime.Today.ToString("dd-MM-yyyy", new CultureInfo("pt-BR")));

                InsertEmailInQueue(template, string.Concat("FP&C Task Calendar – FOLLOW-UP Weekly Inbox @ ", DateTime.Today.ToString("dd/MM/yyyy")), item.WorkEMail, string.Empty);

            }

            CreateControlFile("FollowUp");
        }

        public void SendFollowUpManagerNotification(IEnumerable<TasksDeliverablesItem> tasks, ref ICurrentAction currentAction)
        {
            currentAction.Description = "Follow Up Manager";

            var users = new List<UserInformationListItem>();
            var tasksUpdated = new List<TasksDeliverablesItem>();

            tasks.ToList().ForEach(x =>
            {
                UpdateTaskAndLoadAssignedTo(users, tasksUpdated, x);
            });

            tasks = tasksUpdated;
            var templateMaster = EmailHelper.GetEmailBody(@"\\LACBRA001FS0010\DATA_GRP1\FTOOLS\Apps\CalendarAutomation\HTML\ManagerNotification.htm");
            var templateContentMaster = EmailHelper.GetEmailBody(@"\\LACBRA001FS0010\DATA_GRP1\FTOOLS\Apps\CalendarAutomation\HTML\ManagerNotificationContent.htm");

            var teams = tasks.Select(x => x.OTFPCTeamValue).Distinct();

            foreach (var item in teams)
            {
                var manager = ConfigurationManager.AppSettings[item];

                if (manager == null) continue;
                
                var template = templateMaster;
                var templateContent = templateContentMaster;

                var teamTasks = tasks.Where(x => x.OTFPCTeamValue == item);
                if (teamTasks.Any())
                {   template = FillNotificationContentTemplate("BAU", teamTasks, null, template, templateContent);
                    //template = FillNotificationContentTemplate("VOE", teamTasks, null, template, templateContent);

                    template = template.Replace("[FullName]", string.Format("{0} {1}", manager, ""));
                    template = template.Replace("[DateTime]", DateTime.Today.ToString("dd-MM-yyyy", new CultureInfo("pt-BR")));

                    InsertEmailInQueue(template, string.Concat("FP&C Task Calendar – FOLLOW-UP Weekly Manager Inbox @ ", DateTime.Today.ToString("dd/MM/yyyy")), manager, string.Empty);
                }
                
            }

            SendEmails();
            CreateControlFile("ManagerFollowUp");
        }

        public void SendDashboardEmail(IEnumerable<TasksDeliverablesItem> tasks, string activityType, ref ICurrentAction currentAction)
        {
            currentAction.Description = "Send Dashboard";

            var teams = new List<String>();
            var tasksUpdated = new List<TasksDeliverablesItem>();

            tasks.Where(x => x.ActivityTypeValue == activityType && x.StatusValue == "Completed").ToList().ForEach(x =>
            {
                teams.Add(x.OTFPCTeamValue);
                tasksUpdated.Add(x);
            });

            tasks = tasksUpdated;

            var template = EmailHelper.GetEmailBody(@"\\LACBRA001FS0010\DATA_GRP1\FTOOLS\Apps\CalendarAutomation\HTML\DashboardNotification.htm");

            template = template.Replace("[DateTime]", DateTime.Today.ToString("dd-MM-yyyy", new CultureInfo("pt-BR")));

            var teamTemplate = string.Empty;

            var beforeTarget = 0;
            var onTarget = 0;
            var onLate = 0;

            var totalUpdatedOnTime = 0;
            var totalUpdatedOnLate = 0;

            foreach (var team in teams.Distinct().OrderBy(x => x))
            {
                var templateContent = EmailHelper.GetEmailBody(@"\\LACBRA001FS0010\DATA_GRP1\FTOOLS\Apps\CalendarAutomation\HTML\DashboardContentNotification.htm");

                var filledTemplate = string.Empty;
                var tasksTeam = tasks.Where(x => x.OTFPCTeamValue == team);

                var tasksTotal = tasksTeam.Count();

                var tasksDeliveredBeforeTarget = tasksTeam.Count(x => x.Complete == 1 && x.TargetDate.HasValue && x.DeliveryDate.HasValue
                                                && x.DeliveryDate.Value.Date < x.TargetDate.Value.Date);

                var tasksDeliveredOnTarget = tasksTeam.Count(x => x.Complete == 1 && x.TargetDate.HasValue && x.DeliveryDate.HasValue
                                                && x.DeliveryDate.Value.Date == x.TargetDate.Value.Date);

                var tasksDeliveredAfterTarget = tasksTeam.Count(x => x.Complete == 1 && x.TargetDate.HasValue && x.DeliveryDate.HasValue
                                                && x.DeliveryDate.Value.Date > x.TargetDate.Value.Date);

                var totalTasksDelivered = (tasksDeliveredBeforeTarget + tasksDeliveredOnTarget + tasksDeliveredAfterTarget);

                var percentDeliveredOnTarget = 0;
                if (totalTasksDelivered != 0)
                    percentDeliveredOnTarget = Convert.ToInt32(Math.Round(decimal.Divide((tasksDeliveredBeforeTarget + tasksDeliveredOnTarget) * 100, totalTasksDelivered), 0));

                var tasksUpdatedBeforeTarget = tasksTeam.Count(x => x.Complete == 1 && x.TargetDate.HasValue && x.Modified.HasValue
                                                && x.DeliveryDate.HasValue && x.Modified.Value.Date < x.DeliveryDate.Value.Date);

                var tasksUpdatedOnTarget = tasksTeam.Count(x => x.Complete == 1 && x.TargetDate.HasValue && x.Modified.HasValue
                                                && x.DeliveryDate.HasValue && x.Modified.Value.Date == x.DeliveryDate.Value.Date);

                var tasksUpdatedAfterTarget = tasksTeam.Count(x => x.Complete == 1 && x.TargetDate.HasValue && x.Modified.HasValue
                                                && x.DeliveryDate.HasValue && x.Modified.Value.Date > x.DeliveryDate.Value.Date);

                var totalTasksUpdated = (tasksUpdatedBeforeTarget + tasksUpdatedOnTarget + tasksUpdatedAfterTarget);

                var updatedOnTarget = 0;
                if (totalTasksUpdated != 0)
                    updatedOnTarget = Convert.ToInt32(Math.Round(decimal.Divide((tasksUpdatedOnTarget + tasksUpdatedBeforeTarget) * 100, totalTasksUpdated), 0));

                templateContent = templateContent.Replace("[TeamName]", team);
                templateContent = templateContent.Replace("[TotalOfTasksDeliveredOnTarget]", (tasksDeliveredBeforeTarget + tasksDeliveredOnTarget).ToString());
                templateContent = templateContent.Replace("[TotalOfTasksDeliveredOnTargetPercent]", percentDeliveredOnTarget.ToString());

                templateContent = templateContent.Replace("[TotalOfDeliveredTask]", totalTasksDelivered.ToString());

                templateContent = templateContent.Replace("[DeliveredAfterTarget]", tasksDeliveredAfterTarget.ToString());
                templateContent = templateContent.Replace("[DeliveredAfterTargetPercent]", (100 - percentDeliveredOnTarget).ToString());

                templateContent = templateContent.Replace("[UpdatedOnTarget]", tasksUpdatedOnTarget.ToString());
                templateContent = templateContent.Replace("[UpdatedOnTargetPercent]", updatedOnTarget.ToString());

                templateContent = templateContent.Replace("[UpdatedAfterTarget]", tasksUpdatedAfterTarget.ToString());
                templateContent = templateContent.Replace("[UpdatedAfterTargetPercent]", (100 - updatedOnTarget).ToString());

                templateContent = templateContent.Replace("[BarDeliveryPercent]", GetBarPercent(percentDeliveredOnTarget).ToString());
                templateContent = templateContent.Replace("[BarWidthDeliveryPercent]", percentDeliveredOnTarget.ToString());

                templateContent = templateContent.Replace("[BarUpdatePercent]", GetBarPercent(updatedOnTarget).ToString());
                templateContent = templateContent.Replace("[BarWidthUpdatePercent]", updatedOnTarget.ToString());

                teamTemplate += templateContent;

                beforeTarget += tasksDeliveredBeforeTarget;
                onTarget += tasksDeliveredOnTarget;
                onLate += tasksDeliveredAfterTarget;

                totalUpdatedOnTime += (tasksUpdatedBeforeTarget + tasksUpdatedOnTarget);
                totalUpdatedOnLate += tasksUpdatedAfterTarget;
            }

            template = template.Replace("[TasksBeforeTarget]", beforeTarget.ToString());
            template = template.Replace("[TasksOnTarget]", onTarget.ToString());
            template = template.Replace("[TasksLate]", onLate.ToString());

            template = template.Replace("[TotalUpdatedOnTime]", totalUpdatedOnTime.ToString());
            template = template.Replace("[TotalUpdatedOnLate]", totalUpdatedOnLate.ToString());

            template = template.Replace("[DeliverableAreasContent]", teamTemplate);

            var directManagers = "cb20040;bs24540;es27071;kl51443;ts36751;aa18454;im58154";

            if (DateTime.Today.IsLastFriday())
                InsertEmailInQueue(template, string.Concat("FP&C Task Calendar – [", DateTime.Today.ToString("MMMM"), "] Complete Management Dashboard - ", activityType, " @ ", DateTime.Today.ToString("dd/MM/yyyy")), "md84317;", directManagers);
            else
                InsertEmailInQueue(template, string.Concat("FP&C Task Calendar – [", DateTime.Today.ToString("MMMM"), "] Partial Management Dashboard - ", activityType, " @ ", DateTime.Today.ToString("dd/MM/yyyy")), "md84317", directManagers);

            CreateControlFile("Dashboard");
        }

        public int GetBarPercent(int percentOnTarget)
        {
            var intValue = percentOnTarget / 10;
            return intValue * 10;
        }
        public void UpdateTaskAndLoadAssignedTo(List<UserInformationListItem> users, List<TasksDeliverablesItem> tasksUpdated, TasksDeliverablesItem x)
        {
            try
            {
                Task.DataContext.LoadProperty(x, "AssignedTo");
                x.AssignedTo.ToList().ForEach(y => users.Add(y));
                tasksUpdated.Add(x);
            }
            catch
            {
                UpdateTaskAndLoadAssignedTo(users, tasksUpdated, x);
            }
        }

        public void InsertEmailInQueue(string template, string subject, string to, string cc)
        {
            //to = "fc16291";
            //cc = "fc16291";

            Emails.Add(new EmailSenderWcf.Email
            {
                BodyMessage = template,
                Subject = subject,
                SentOnBehalfOfName = "O&T Finance Comunica",
                To = string.IsNullOrWhiteSpace(to) ? null : to.Split(";").Select(x => new EmailSenderWcf.EmailAddress { Description = x }).ToList(),
                Cc = string.IsNullOrWhiteSpace(cc) ? null : cc.Split(";").Select(x => new EmailSenderWcf.EmailAddress { Description = x }).ToList(),
                ApplicationName = "Calendar Tasks",
                Url = string.Empty,
                Parameters = new Dictionary<string, string>()
            });
        }

        public void SendEmails()
        {
            using (var client = new EmailClient())
            {
                client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;

                //var email = new EmailSenderWcf.Email
                //{
                //    BodyMessage = template,
                //    Subject = subject,
                //    SentOnBehalfOfName = "O&T Finance Comunica",
                //    To = string.IsNullOrWhiteSpace(to) ? null : to.Split(";").Select(x => new EmailSenderWcf.EmailAddress { Description = x }).ToList(),
                //    Cc = string.IsNullOrWhiteSpace(cc) ? null : cc.Split(";").Select(x => new EmailSenderWcf.EmailAddress { Description = x }).ToList(),
                //    ApplicationName = "Calendar Tasks",
                //    Url = string.Empty,
                //    Parameters = new Dictionary<string, string>()
                ////};

                foreach (var email in Emails)
                    client.InsertEmailInQueue(email);
            }
        }

        public void CreateControlFile(string fileName)
        {
            var fileNameWithDate = string.Concat(fileName, DateTime.Now.ToString("yyyyMMdd"));

            if (!File.Exists(string.Concat(PathFolder, fileNameWithDate)))
                File.Create(string.Concat(PathFolder, fileNameWithDate));
        }
        public bool VerifyControlFile(string fileName)
        {
            if (File.Exists(string.Concat(PathFolder, string.Concat(fileName, DateTime.Now.ToString("yyyyMMdd")))))
                return true;
            else
                return false;
        }

        public string ReplaceDashboardContent(string template, TasksDeliverablesItem task)
        {
            var templateEdited = template.Replace("[TeamName]", task.OTFPCTeamValue);

            return templateEdited;
        }

        public string ReplaceNotificationContent(string template, TasksDeliverablesItem task)
        {
            var templateEdited = template.Replace("[Activity]", string.Concat("      ", task.Title.ToString().Trim()));
            templateEdited = templateEdited.Replace("[DueDate]", task.TargetDate.Value.ToString("dd/MM/yyyy"));
            templateEdited = templateEdited.Replace("[Days]", task.TargetDate.Value.BusinessDaysTo(DateTime.Today).ToString());

            var users = string.Empty;

            foreach (var user in task.AssignedTo)
                users += string.Concat(user.FirstName, " ", user.LastName, "; ");

            templateEdited = templateEdited.Replace("[Responsible]", !string.IsNullOrWhiteSpace(users) ? users.Substring(0, users.Length - 2) : "Not Assigned");

            return templateEdited;
        }

        public void GenerateExcelReport(IEnumerable<TasksDeliverablesItem> tasks, ref ICurrentAction currentAction)
        {

            currentAction.Description = "Generate Excel";

            using (ExcelPackage excelPackage = new ExcelPackage(new FileInfo(@"\\LACBRA001FS0010\DATA_GRP1\FTOOLS\Apps\CalendarAutomation\Template\Controle_Entregas_OTFPC_v2.xlsx"), true))
            {
                ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets[1];

                var initialRow = 4;

                foreach (var task in tasks.Where(x => x.Complete == 1 && x.StatusValue == "Completed")) // x.Complete == 1 && x.StatusValue == "Completed"))
                {
                    worksheet.Cells[initialRow, 3].Value = task.Title;
                    worksheet.Cells[initialRow, 3].Style.Font.Size = 9;
                    worksheet.Cells[initialRow, 3].Style.Font.Name = "Calibri";

                    worksheet.Cells[initialRow, 4].Value = "M";
                    worksheet.Cells[initialRow, 4].Style.Font.Size = 9;
                    worksheet.Cells[initialRow, 4].Style.Font.Name = "Calibri";

                    worksheet.Cells[initialRow, 6].Value = task.OTFPCTeamValue;
                    worksheet.Cells[initialRow, 6].Style.Font.Size = 9;
                    worksheet.Cells[initialRow, 6].Style.Font.Name = "Calibri";

                    worksheet.Cells[initialRow, 10].Value = task.TargetDate;
                    worksheet.Cells[initialRow, 10].Style.Font.Size = 9;
                    worksheet.Cells[initialRow, 10].Style.Font.Name = "Calibri";

                    worksheet.Cells[initialRow, 11].Value = task.DeliveryDate;
                    worksheet.Cells[initialRow, 11].Style.Font.Size = 9;
                    worksheet.Cells[initialRow, 11].Style.Font.Name = "Calibri";

                    initialRow += 1;
                }

                string inputFile = (@"\\LACBRA001FS0010\DATA_GRP1\FTOOLS\Apps\CalendarAutomation\input\");
                string file = string.Concat(inputFile, "Controle_Entregas_OTFPC_", DateTime.Now.ToString("yyyyMMdd"), ".xlsx");

                System.IO.Directory.GetFiles(inputFile).ToList().ForEach(x => System.IO.File.Delete(x));

                Byte[] bin = excelPackage.GetAsByteArray();
                System.IO.File.WriteAllBytes(file, bin);

            }

        }

    }
}
